import Utils from '../utils/index';
import Http from '../utils/Http';
import config from '../config';


class GanttCache {
   constructor() {
      this.reset();
   }

   // 清空所以数据
   reset() {
      this.database = {};
   }

   /**
    * 增加数据
    * @param {string} table 表名
    * @param {Array | Object} data 数据
    * @param {boolean | undefined} reset 是否先清空数据表
    */
   insert(table, data, reset) {
      if (reset || !this.database[table]) {
         this.database[table] = {};
      }
      if (!Utils.isArr(data)) {
         data = [data];
      }
      let i = 0,
         total = data.length;

      for (; i < total; i++) {
         this.database[table][data[i].sid] = Utils.deleteNeedlessProp(data[i]);
      }
   }

   /**
    * 增加对象数据
    * @param {object} 数据
    * @param {boolean} 是否重置数据库
    */
   addObjectData(data, reset) {
      if (reset) {
         this.reset();
      }
      let key = null,
         i = 0,
         total = 0,
         d = null;
      for (key in data) {
         if (!this.database[key]) {
            this.database[key] = {};
         }
         d = data[key];
         total = d.length;
         for (i = 0; i < total; i++) {
            this.database[key][d[i].sid] = Utils.deleteNeedlessProp(d[i]);
         }
      }
   }

   /**
    * 删除数据
    * @param {string} table 表名
    * @param {string | Array} 主键或主键数组
    */
   remove(table, ids) {
      if (!this.database[table]) {
         return false;
      }

      if (Utils.isArr(ids)) {
         ids.forEach(id => {
            delete this.database[table][id]
         });
      } else {
         delete this.database[table][ids];
      }
   }

   /**
    * 通过条件删除所有数据
    * @param {string} table 表名
    * @param {function | undefined} filter 过滤函数
    */
   removeAll(table, filter) {
      if (!filter) {
         this.database[table] = {};
      } else {
         for (let key in this.database[table]) {
            if (filter(this.database[table][key])) {
               delete this.database[table][key];
            }
         }
      }
   }

   /**
    * 更新数据
    * @param {string} table 表名
    * @param {object} 数据
    * @param {boolean} isMerge 是否是合并操作（全量更嗨还是部分更新）
    */
   update(table, data, isMerge) {
      if(!data || !data.sid) {
         return false;
      }
      if(!this.database[table]){
        this.database[table]={};
     }
      Utils.deleteNeedlessProp(data);
      if (!isMerge) {
         this.database[table][data.sid] = data;
      } else {
         this.database[table][data.sid] = Utils.extend(this.database[table][data.sid], data);
      }
   }

   updateAll(table, data, isMerge) {
      data.forEach(d => {
         this.update(table, d, isMerge);
      });
   }

   /**
    * 查询数据
    * @param {string} table 表名
    * @param {function | undefined} filter 过滤函数
    */
   getAll(table, filter) {
      let data = this.database[table],
         result = [],
         sid = null;
      if (data && !Utils.isObjEmpty(data)) {
         for (sid in data) {
            if (!filter || filter(data[sid])) {
               result.push(data[sid]);
            }
         }
      }
      return result;
   }

   /**
    * 通过主键查询数据
    * @param {string} table 表名
    * @param {interge} id 主键
    */
   getById(table, id) {
      return this.database[table] && this.database[table][id];
   }

   /**
    * 通过索引查询数据
    * @param {string} table 表名
    * @param {string} index 索引
    * @param {any} indexValue 索引值
    */
   getByIndex(table, index, indexValue) {
      return this.getAll(table, d => {
         return d[index] === indexValue;
      });
   }

   /**
    * ****************************************************************************************
    * 业务相关操作
    * ****************************************************************************************
    */

   /**
    * 读取主数据并写入到数据库
    */
   loadData(callback) {
      Http.get(config.api.masterData, null, data => {
         this.addObjectData(data, true);
         callback();
      });
   }

   updateCastByHeats(heatSids, callback = Utils.noop) {
      if (heatSids.length === 0) {
         return false;
      }
      Http.post(config.api.castDataByheats, JSON.stringify(heatSids), data => {
         this.updateCastHeat(data);
         callback();
      });
   }

   // 更新浇次炉次缓存
   updateCastHeat(data) {
      this.updateMasterSlaveData(data, 'casts', 'heats');
   }
   /**
    * 通过 Heat Sid 查找浇次信息
    * @param {number} heatSid 炉次 Sid
    * @returns {object} 包含浇次 和 炉次信息的对象
    */
   getCastHeatByHeatSid(heatSid) {
      let heat = this.getById('heats', heatSid),
         cast = this.getById('casts', heat.castSid);
      return {
         heat: heat,
         cast: cast
      }
   }

   getHeatsByHeatSid(heatSid) {
      let heat = this.getById('heats', heatSid);
      return this.getByIndex('heats',  'castSid', heat.castSid);
   }



   // 更新操作数据缓存
   updateOperationsRute(data) {
      if (!Utils.isArr(data)) {
         data = [data];
      }
      this.updateMasterSlaveData(data, 'operationRoute', 'operations', {
         masterObjKey: 'operationRoute',
         masterObjIndex: 'routeSid'
      });
   }

   /**
    * 主从数据更新
    * @param {*} masterTable 主表名
    * @param {*} slaveTable  从表名
    * @param {object} options 配置，包含
    *    masterObjKey 默认是 masterTable 去掉最后的 's'，例如 casts，对应的取返回的数据是 cast
    *    masterObjIndex
    */
   updateMasterSlaveData(data, masterTable, slaveTable, options) {
      if (!data || data.length === 0) {
         return false;
      }

      let i = 0,
         total = data.length,
         d = null,
         masterObjKey = (options && options.masterObjKey) || masterTable.substring(0, masterTable.length - 1),
         masterObjIndex = (options && options.masterObjIndex) || (masterObjKey + 'Sid'),
         masterData = null,
         slaveData = null;

      for (; i < total; i++) {
         d = data[i];
         masterData = d[masterObjKey];
         slaveData = d[slaveTable];

         if (this.getById(masterTable, masterData.sid)) {
            this.update(masterTable, masterData);
            this.deleteSlaveDataByMaster(slaveTable, masterObjIndex, masterData.sid);
         } else {
            this.insert(masterTable, masterData);
         }

         if (!slaveData || slaveData.length === 0) {
            continue;
         }
         this.insert(slaveTable, slaveData);
      }
   }


   /**
    * 删除和主数据关联的从数据
    * @param {objectStore} 从数据的 objectStroe,
    * @param {string} 从数据对应主数据的索引 key，默认是 从数据名称 + Sid ，例如 (castSid)
    * @param {string | number} 索引值
    */
   deleteSlaveDataByMaster(slaveObjectStore, masterIndexKey, masterIndexValue) {
      this.removeAll(slaveObjectStore, d => {
         return d[masterIndexKey] === masterIndexValue;
      });
   }


   /**
    * 清除主从数据
    */
   clearMasterSlaveData(masterTable, slaveTable, masterDataSid, options) {
      let i = 0,
         total = masterDataSid.length,
         masterObjKey = (options && options.masterObjKey) || masterTable.substring(0, masterTable.length - 1),
         masterObjIndex = (options && options.masterObjIndex) || (masterObjKey + 'Sid');

      for (; i < total; i++) {
         this.deleteSlaveDataByMaster(slaveTable, masterObjIndex, masterDataSid[i]);
         this.remove(masterTable, masterDataSid[i])
      }
   }

}

export default GanttCache;
